<?php defined('SYSPATH') or die('No direct script access.');

class PHPBarcode {
  private $bar_color;
  private $bg_color;
  private $text_color;
  private $font_loc;
  
  static function &factory()
  {
    $cname = __CLASS__;
    $o = new $cname();
    return $o;
  }
  function __construct()
  {
    $this->bar_color=Array(0,0,0);
    $this->bg_color=Array(255,255,255);
    $this->text_color=Array(0,0,0);
    $this->font_loc = DOCROOT."a/css/arial.ttf";
  }

/*

 * Built-In Encoders
 * Part of PHP-Barcode 0.4
 
 * (C) 2001,2002,2003,2004,2011 by Folke Ashberg <folke@ashberg.de>
 
 * The newest version can be found at http://www.ashberg.de/php-barcode
 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 */

function barcode_gen_ean_sum($ean){
  $even=true; $esum=0; $osum=0;
  for ($i=strlen($ean)-1;$i>=0;$i--){
	if ($even) $esum+=$ean[$i];	else $osum+=$ean[$i];
	$even=!$even;
  }
  return (10-((3*$esum+$osum)%10))%10;
}

/* barcode_encode_ean(code [, encoding])
 *   encodes $ean with EAN-13 using builtin functions
 *
 *   return:
 *    array[encoding] : the encoding which has been used (EAN-13)
 *    array[bars]     : the bars
 *    array[text]     : text-positioning info
 */
function barcode_encode_ean($ean, $encoding = "EAN-13"){
    $digits=array(3211,2221,2122,1411,1132,1231,1114,1312,1213,3112);
    $mirror=array("000000","001011","001101","001110","010011","011001","011100","010101","010110","011010");
    $guards=array("9a1a","1a1a1","a1a");

    $ean=trim($ean);
    if (preg_match("#[^0-9]#i",$ean)){
	return array("text"=>"Invalid EAN-Code");
    }
    $encoding=strtoupper($encoding);
    if ($encoding=="ISBN"){
	if (!preg_match("#^978#", $ean)) $ean="978".$ean;
    }
    if (preg_match("#^978#", $ean)) $encoding="ISBN";
    if (strlen($ean)<12 || strlen($ean)>13){
	return array("text"=>"Invalid $encoding Code (must have 12/13 numbers)");
    }

    $ean=substr($ean,0,12);
    $eansum=$this->barcode_gen_ean_sum($ean);
    $ean.=$eansum;
    $line=$guards[0];
    for ($i=1;$i<13;$i++){
	$str=$digits[$ean[$i]];
	if ($i<7 && $mirror[$ean[0]][$i-1]==1) $line.=strrev($str); else $line.=$str;
	if ($i==6) $line.=$guards[1];
    }
    $line.=$guards[2];

    /* create text */
    $pos=0;
    $text="";
    for ($a=0;$a<13;$a++){
	if ($a>0) $text.=" ";
	$text.="$pos:12:{$ean[$a]}";
	if ($a==0) $pos+=12;
	else if ($a==6) $pos+=12;
	else $pos+=7;
    }

    return array(
		"encoding" => $encoding,
		"bars" => $line,
		"text" => $text
		);
}

/* 
 * barcode_outimage(text, bars [, scale [, mode [, total_y [, space ]]]] )
 *
 *  Outputs an image using libgd
 *
 *    text   : the text-line (<position>:<font-size>:<character> ...)
 *    bars   : where to place the bars  (<space-width><bar-width><space-width><bar-width>...)
 *    scale  : scale factor ( 1 < scale < unlimited (scale 50 will produce
 *                                                   5400x300 pixels when
 *                                                   using EAN-13!!!))
 *    mode   : png,gif,jpg, depending on libgd ! (default='png')
 *    total_y: the total height of the image ( default: scale * 60 )
 *    space  : space
 *             default:
 *		$space[top]   = 2 * $scale;
 *		$space[bottom]= 2 * $scale;
 *		$space[left]  = 2 * $scale;
 *		$space[right] = 2 * $scale;
 */


function barcode_outimage($text, $bars, $scale = 1, $mode = "png",
	    $total_y = 0, $space = ''){
    /* set defaults */
    if ($scale<1) $scale=2;
    $total_y=(int)($total_y);
    if ($total_y<1) $total_y=(int)$scale * 60;
    if (!$space)
      $space=array('top'=>2*$scale,'bottom'=>2*$scale,'left'=>2*$scale,'right'=>2*$scale);
    
    /* count total width */
    $xpos=0;
    $width=true;
    for ($i=0;$i<strlen($bars);$i++){
	$val=strtolower($bars[$i]);
	if ($width){
	    $xpos+=$val*$scale;
	    $width=false;
	    continue;
	}
	if (preg_match("#[a-z]#", $val)){
	    /* tall bar */
	    $val=ord($val)-ord('a')+1;
	} 
	$xpos+=$val*$scale;
	$width=true;
    }

    /* allocate the image */
    $total_x=( $xpos )+$space['right']+$space['right'];
    $xpos=$space['left'];
    if (!function_exists("imagecreate")){
	throw new Kohana_Exception("You don't have the gd2 extension enabled.");
	return "";
    }
    $im=imagecreatetruecolor($total_x, $total_y);
    /* create two images */
    $col_bg=ImageColorAllocate($im,$this->bg_color[0],$this->bg_color[1],$this->bg_color[2]);
    $col_bar=ImageColorAllocate($im,$this->bar_color[0],$this->bar_color[1],$this->bar_color[2]);
    $col_text=ImageColorAllocate($im,$this->text_color[0],$this->text_color[1],$this->text_color[2]);
    $height=round($total_y-($scale*10));
    $height2=round($total_y-$space['bottom']);
    imagefilledrectangle($im,0,0,$total_x,$total_y,$col_bg);

    /* paint the bars */
    $width=true;
    for ($i=0;$i<strlen($bars);$i++){
	$val=strtolower($bars[$i]);
	if ($width){
	    $xpos+=$val*$scale;
	    $width=false;
	    continue;
	}
	if (preg_match("#[a-z]#", $val)){
	    /* tall bar */
	    $val=ord($val)-ord('a')+1;
	    $h=$height2;
	} else $h=$height;
	imagefilledrectangle($im, $xpos, $space['top'], $xpos+($val*$scale)-1, $h, $col_bar);
	$xpos+=$val*$scale;
	$width=true;
    }
    /* write out the text */
    $chars=explode(" ", $text);
    reset($chars);
    while (list($n, $v)=each($chars)){
	if (trim($v)){
	    $inf=explode(":", $v);
	    $fontsize=$scale*($inf[1]/1.8);
	    $fontheight=$total_y-($fontsize/2.7)+2;
	    @imagettftext($im, $fontsize, 0, $space['left']+($scale*$inf[0])+2,
	    $fontheight, $col_text, $this->font_loc, $inf[2]);
	}
    }

  return $im;
}

	function render($code, $encoding="ANY", $scale = 2 ,$mode = "png", $output_file = NULL )
	{
    $r = Request::current()->response();
    /* use built-in EAN-Encoder */
    $bars=$this->barcode_encode_ean($code, $encoding);
    $im = $this->barcode_outimage($bars['text'],$bars['bars'],$scale, $mode);
    // Kohana::$log->add(Log::INFO,Debug::vars($bars,$im));

  $r = Request::current();
  
    /* output the image */
    $mode=strtolower($mode);
    if ($mode=='jpg' || $mode=='jpeg'){
	if (is_null($output_file)) $r->response()->headers('Content-Type', 'image/jpeg; name="barcode.jpg"');
	$retval = imagejpeg($im, $output_file);
    } else if ($mode=='gif'){
	if (is_null($output_file)) $r->response()->headers('Content-Type', 'image/gif; name="barcode.gif"');
	$retval = imagegif($im, $output_file);
    } else {
	if (is_null($output_file)) $r->response()->headers('Content-Type', 'image/png; name="barcode.png"');
	$retval = imagepng($im, $output_file);
    }
    $r->response()->check_cache(NULL, $r);
    imagedestroy($im);
    
    return $retval;
	}
}
